#ifndef POINTCLOUD_H
#define POINTCLOUD_H

#include <stdlib.h>
#include <vector>

#include "HoughSpace.h"
#include "Point.h"
#include "Circle.h"

/**
 * \file PointCloud.h
 * \brief Fichier contenant la déclaration de la classe PointCloud.
 */

using namespace std;

class PointCloud
{
	/* \class PointCloud
	 * \brief Classe représentant un nuage de points selon les coordonnées x,y,z et les couleurs r,g,b.
	 */
	
	private :

	vector<Point> ListePoints;							/*!<Tableau de points contenant les points du nuage*/

	public :

	/*!
	*  \brief Constructeur de la classe PointCloud
	*
	*  Constructeur de la classe PointCloud
	*/
    PointCloud(void);
    
	/*!
	*  \brief Constructeur de la classe PointCloud
	*
	*  Constructeur de la classe PointCloud
	*
	* \param _c : le nuage de points ainsi construit sera une copie du nuage de points _c.
	*/
	PointCloud(const PointCloud & _c);
    
	/*!
	*  \brief Constructeur de la classe PointCloud
	*
	*  Constructeur de la classe PointCloud à partir d'un fichier
	*
	* \param _filename : Nom du fichier à lire.
	*/
	PointCloud(char *_filename);

	/*!
	*  \brief Destructeur de la classe PointCloud
	*
	*  Destructeur de la classe PointCloud
	*/
	~PointCloud();

	/*!
	*  \brief Affiche le nuage de points.
	*
	*  Affiche le nuage de points.
	*
	* \return : void
	*/
	void displayPointCloud ();
	
	/*!
	*  \brief Affiche le nuage de points en couleur.
	*
	*  Affiche le nuage de points de la couleur (r,g,b).
	*
	*  \param _r : valeur du canal rouge.
	*  \param _g : valeur du vert rouge.
	*  \param _b : valeur du bleu rouge.
	*
	* \return : void
	*/
	void displayPointCloud ( float _r, float _g, float _b);
	
	/*!
	*  \brief Ecrit dans la console les coordonnées ainsi que la couleur de tous les points du nuage.
	*
	*  Ecrit dans la console les coordonnées ainsi que la couleur de tous les points du nuage.
	*
	* \return : void
	*/
	void printPointCloud ();
	
	/*!
	*  \brief Ajoute un Point au nuage de point.
	*
	*  Ajoute un Point au nuage de point.
	*
	* \param _p : le point à ajouter au nuage.
	*
	* \return : void
	*/
	void add(Point _p);
	
	/*!
	*  \brief Accede à un point du nuage.
	*
	*  Accede à un point du nuage.
	*
	* \param _i : numéro du Point auquel on cherche à accéder.
	*
	* \return : Renvoie le point numéro _i du nuage.
	*/
	Point get(int _i);
	
	/*!
	*  \brief Vide le nuage de points.
	*
	*  Vide le nuage de points.
	*/
	void clear(void);
	
	/*!
	*  \brief Accede à la taille du nuage de points.
	*
	*  Accede à la taille du nuage de points.
	*
	* \return : Renvoie la taille du nuage de points (le nombre de points qu'il contient).
	*/
	int size(void);
	
	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points.
	 *
     *  Remplit le tableau de cercles à partir des triplets de points trouvés dans le nuage de points.
	 *
	 *  \param _tabCircles : vector de cercles à remplir.
	 *
	 *  \return : void
     */
	void getCircles(vector <Circle> & _tabCircles);

	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points.
	 *
     *  Remplit directement l'espace de Hough à partir des triplets de points trouvés dans le nuage de points.
	 *
	 *  \param _hs : Espace de Hough à remplir.
	 *  \param _rMax : Rayon max des cercles à chercher.
	 *
	 *  \return : void
     */
	void getCircles(HoughSpace & _hs, float _rMax);

	/*!
     *  \brief Récupère l'ensemble des cercles à partir du nuage de points.
	 *
     *  Remplit directement l'espace de Hough à partir des triplets de points trouvés dans le nuage de points en appliquant un certain coefficient.
	 *
	 *  \param _hs : Espace de Hough à remplir.
	 *  \param _rMax : Rayon max des cercles à chercher.
	 *  \param _coef : Coefficiant permettant de donner plus ou moins de poid aux cercles trouvés.
	 *
	 *  \return : void
     */
	void getCircles(HoughSpace & _hs, float _rMax, int _coef);
	
	/*!
	 *  \brief Surcharge de d'opérateur.
	 *
	 *  Surcharge de l'opérateur =.
	 *
	 *  \param _c : Nuage de points à copier.
	 *
	 *  \return : PointCloud
	*/
	PointCloud &operator= (const PointCloud &_c);
	
	/*!
	*  \brief Accede à la hauteur minimale du nuage de points.
	*
	*  Accede à la hauteur minimale du nuage de points.
	*
	* \return : Renvoie la hauteur minimale du nuage de points.
	*/
	float getZMin ();
	
	/*!
	*  \brief Accede au Point de hauteur minimale du nuage de points.
	*
	*  Accede au Point de hauteur minimale du nuage de points.
	*
	* \return : Renvoie le point le plus bas du nuage.
	*/
	Point getPointMin ();
	
	/*!
	*  \brief Ne garde du nuage de points que ceux compris entre deux hauteurs. Le nuage de points initial est détruit est remplacé par un autre ne contenant que les points souhaités.
	*
	*  Ne garde du nuage de points que ceux compris entre deux hauteurs.
	*
	* \param _zMin : hauteur minimale des points à conserver.
	* \param _zMin : hauteur maximale des points à conserver.
	*
	* \return : void
	*/
	void keepPointsBetween ( float _zMin, float _zMax);
	
	/*!
	*  \brief Déplace le nuage de points vers l'origine (le point (0,0,0) du repère OpenGL).
	*
	*  Déplace le nuage de points de manière à ce que le point le coin inférieur gauche de la boite englobante du nuage soit situé au point (0,0,0) du repère.
	*
	* \param _xMin : Abcsisse minimale du nuage de points.
	* \param _yMin : Ordonnée minimale du nuage de points.
	* \param _zMin : Hauteur minimale du nuage de points.
	*
	* \return : void
	*/
	void setOrigin ( float _xMin, float _yMin, float _zMin );
	
	/*!
     *  \brief Fait une coupe du nuage de points.
	 *
     *  Coupe le nuage de points à partir de deux seuils.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *
	 *  \return : void
     */
	void keepSlice ( float _bas , float _haut );
	
	/*!
     *  \brief Fait une coupe du nuage de points.
	 *
     *  Coupe le nuage de points en récupérant un certain nombre de points à partir d'un seuil.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : void
     */
	void keepSlice(float _bas, int _nbPoints );
	
	/*!
     *  \brief Fait une coupe du nuage de points.
	 *
     *  Coupe le nuage de points en récupérant un certain nombre de points compris entre une hauteur minimale et maximale.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : void
     */
	void keepSlice(float _bas, float _haut, int _nbPoints );
	
	/*!
     *  \brief Crée une coupe du nuage de points.
	 *
     *  Crée un nouveau PointCloud contenant une coupe du nuage de points à partir de deux seuils.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *
	 *  \return : Nouveau PointCloud contenant la coupe. 
     */
	PointCloud getSlice ( float _bas, float _haut );

	/*!
     *  \brief Crée une coupe du nuage de points.
	 *
     *  Crée un nouveau PointCloud contenant une coupe du nuage de points en récupérant un certain nombre de points à partir d'un seuil.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : Nouveau PointCloud contenant la coupe.
     */
	PointCloud getSlice ( float _bas, int _nbPoints );
	
	/*!
     *  \brief Crée une coupe du nuage de points.
	 *
     *  Crée un nouveau PointCloud contenant une coupe du nuage de points en récupérant un certain nombre de points à partir d'un seuil.
	 *
	 *  \param _bas : Seuil bas.
	 *  \param _haut : Seuil haut.
	 *  \param _nbPoints : Nombre de points à récupérer au dessus de l'altitude seuil.
	 *
	 *  \return : Nouveau PointCloud contenant la coupe.
     */
	PointCloud getSlice ( float _bas, float _haut, int _nbPoints );
	
	/*!
	*  \brief Trie les points du nuage selon leur altitude.
	*
	* \return : void
	*/
	void Sort();

	
};

#endif
